home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Essentials / Developer Essentials Nov 90 / Apple II / Apple.II.partition / Utilities / rTutors / part3.3 / rTutor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-19  |  15.9 KB  |  373 lines  |  [TEXT/pdos]

  1. /* PROGRAM R.Tutor  */
  2. /* (a home-grown tutorial for writing applications using resources */
  3. /* Part 1 - starting up & shutting down the tools from a ToolStartup */
  4. /*          list kept in a resource */
  5. /* Part 2 - add a menu bar that is kept in a resource */
  6. /* Part 3 - add the event loop so that the menus "come alive" and put up a */
  7. /*          window that is defined in the resource fork */
  8. /* Part 3.2 - change "About" box from a simple beep into an Alert Window and */
  9. /*            redo the Rez and MAKE file so that we can avoid re-compiling */
  10. /*            the the parts that haven't changed and also to show off some */
  11. /*            of Rez's special abilities such as including already compiled */
  12. /*            resources from another file and appending Rez's output to an */
  13. /*            already existing resource without wiping out the existing */
  14. /*            resources... */
  15. /* Part 3.3 - tossed out the seperate Rez file that showed how to include */
  16. /*            pre-compiled resources and the "-a" flag.  If you want to know */
  17. /*            how those are done, see Part 3.2's source.  I also tossed the */
  18. /*            controls out of the window and put some icons in the window.  */
  19. /*            Naturally, the icons are stored as resources. I've also */
  20. /*            slipped in a special cursor that's kept as a resource also - */
  21. /*            mainly to show people how to use the current definition of how */
  22. /*            an rCursor should be defined (the bit map for an rCursor is */
  23. /*            done differently from the bitmap for an rIcon). */
  24.  
  25. #include <types.h>
  26. #include <INTMATH.h>
  27. #include <MEMORY.h>
  28. #include <MISCTOOL.h>
  29. #include <LOCATOR.h>
  30. #include <DESK.H>
  31. #include <QUICKDRAW.h>
  32. #include <EVENT.h>
  33. #include <CONTROL.h>
  34. #include <WINDOW.h>    
  35. #include <MENU.h>    
  36. #include <GSOS.h>
  37. #include <Resources.h>
  38. #include <QDAux.h>      /* added for part 3.3 */
  39.  
  40. #define  kStartStopID    1L    /* used when starting and shutting down tools */
  41.  
  42. /*---------------------- Menus & Menu Bars ---------------------------*/
  43. #define  kMenuBarID      1L   /* resource ID of the menu bar itself */
  44.  
  45.     /* define all the menu id's */
  46. #define  kAppleMenuID   1000  /* resource ID of the Apple menu */
  47. #define  kFileMenuID    2000  /* resource ID of the File menu */
  48. #define  kEditMenuID    3000  /* resource ID of the Edit menu */
  49.  
  50.     /* now, define the menu item id's */
  51. #define   kAboutBoxID   1001  /* resource ID of the About Box menu item */ 
  52.  
  53. #define   kNewItemID    2001  /* resource ID of the New Item in File menu */
  54. #define   kOpenItemID   2002  /* resource ID of the Open item in File menu */ 
  55. #define   kCloseItemID   255  /* the "Close" item */
  56. #define   kSaveItemID   2004  /* the "Save" item */
  57. #define   kSaveAsItemID 2005  /* the "Save As..." item */
  58. #define   kRevertItemID 2006  /* the "Revert to Saved" item */
  59. #define   kPageItemID   2007  /* the "Page Setup..." item */
  60. #define   kPrintItemID  2008  /* the "Print..." item */
  61. #define   kQuitItemID   2009  /* the "Quit" item */
  62.  
  63. #define   kUndoItemID      250  /* the "Undo" item */
  64. #define   kCutItemID       251  /* the "Cut" item */
  65. #define   kCopyItemID      252  /* the "Copy" item */
  66. #define   kPasteItemID     253  /* the "Paste" item */
  67. #define   kClearItemID     254  /* the "Clear" item */
  68. #define   kSelectItemID   3001  /* the "Select All" item */
  69. #define   kShowClipItemID 3002  /* the "Show ClipBoard" item */
  70.  
  71.     /* define the resource ID's for all windows used by this app */
  72. #define myWindowID    2362L  /* window's resource ID = 2362 */
  73.  
  74. /* declare the constants for our TaskMaster event mask */
  75. #define   kMyTaskMask    0x001FFFFFL  /* this mask is for TaskMaster itself */
  76. #define   kMyEventMask    0xFFFF      /* this mask is passed to GetNextEvent */
  77.  
  78. /* define the constants used for the cursors */
  79. #define rFirstCursor   1  /* added for part 3.3 */
  80.  
  81. /* define the constant used to represent the first icon we're adding */
  82. /* added for part 3.3 */
  83. #define kFloorIcon 1  /* ID of the icon used as the "floor" */
  84.  
  85. /* declare the global variable that we'll use with TaskMaster */
  86. WmTaskRec    gMyEvent;
  87.  
  88.     
  89. /* declare all of the global variables that we'll be using */    
  90. unsigned   gMyMemID;    /* holds the ID returned by MMStartup */
  91. Ref       gToolListRef; /* list of tools used to start and stop the tools */
  92. Boolean   gPunt;        /* TRUE if it's time to quit the app */
  93. word    gWhichCursor;   /* used to tell which of four cursors to use */
  94. CursorHndl grCursorHndl; /* used to hold handle to rCursor */
  95.  
  96.  
  97. /* ------------------------------------------------------------------------ */
  98. /* the following procedure is responsible for putting up the About box */
  99.  
  100. #define kAboutStr    100L /* define the constant for the About box's string */
  101.  
  102. do_show_about()
  103. {    
  104.     /* change the beep into an Alert Window - grab the Alert from a resource */
  105.     word pickedButton;
  106.     pickedButton = AlertWindow(0x0004,   /* alert string is in resource fork */
  107.                                            /* and is a "C" string */
  108.                                NULL,       /* not used right now */
  109.                                kAboutStr); /* resource ID of Alert's string */
  110. }
  111.  
  112.  
  113. /* ------------------------------------------------------------------------ */
  114. /* the following procedure is responsible for quitting the app */
  115.  
  116. do_quit_app()
  117. {
  118.   /* we actually just set the "quit" flag and let the real quitting happen */
  119.   /* in the main event loop.  Later, we would add code here to cope with */
  120.   /* closing all open windows, saving their contents, etc. */
  121.     
  122.     gPunt = TRUE;
  123. }
  124.  
  125.  
  126. /* ------------------------------------------------------------------------ */
  127. /* the following procedure is responsible for dealing with items picked */
  128. /* from the menus by the user */
  129.  
  130. do_menu_events()
  131. {
  132.  
  133.  unsigned int   pickedMenuID; /*ID of menu the user just picked an item from */
  134.  unsigned int   pickedItemID; /* ID of item the user just picked */
  135.  
  136.  /* the hi-word of wmTaskData is the menu ID */
  137.  pickedMenuID = HiWord(gMyEvent.wmTaskData);
  138.  
  139.  /* the lo-word of wmTaskData is the item ID */
  140.  pickedItemID = LoWord(gMyEvent.wmTaskData);
  141.     
  142.     switch(pickedItemID) 
  143.     {
  144.      case kAboutBoxID : do_show_about();    /* show the About box */
  145.                           break;
  146.      case kNewItemID    : break;            /* that's all for this item */
  147.      case kOpenItemID   : break;            /* that's all for this item */
  148.      case kCloseItemID  : break;            /* that's all for this item */
  149.      case kSaveItemID   : break;            /* that's all for this item */
  150.      case kSaveAsItemID : break;            /* that's all for this item */
  151.      case kRevertItemID : break;            /* that's all for this item */
  152.      case kPageItemID   : break;            /* that's all for this item */
  153.      case kPrintItemID  : break;            /* that's all for this item */
  154.      case kQuitItemID   : do_quit_app();    /* sets gPunt to TRUE  */
  155.                           break;
  156.      case kUndoItemID   : break;            /* that's all for this item */
  157.      case kCutItemID    : break;            /* that's all for this item */
  158.      case kCopyItemID   : break;            /* that's all for this item */
  159.      case kPasteItemID  : break;            /* that's all for this item */
  160.      case kClearItemID  : break;            /* that's all for this item */
  161.      case kSelectItemID : break;            /* that's all for this item */
  162.      case kShowClipItemID : break;          /* that's all for this item */
  163.         
  164.      default: ; /* always have a default action in case something goes wrong */
  165.  
  166.     } /* end of the "switch" statement */
  167.  
  168.     /* Turn off the highlighting on the menu the user picked the item from. */
  169.     /* Then return to the main event loop to see what we'll do next. */
  170.     HiliteMenu(FALSE,pickedMenuID);
  171. }
  172.  
  173.  
  174. /* ------------------------------------------------------------------------ */
  175. /* the following procedure installs the menu bar from a resource */
  176.  
  177. do_make_menus()
  178.    MenuBarRecHndl my_mbar_hndl;
  179.    word menu_bar_height; 
  180.   { 
  181.  
  182.    /* the next three calls are ALL required to bring the menu bar in from */
  183.    /* the resource fork AND make it the current system menu bar.  For */
  184.    /* details, see the IIGS Toolbox Reference, under NewMenuBar2  */
  185.   my_mbar_hndl = NewMenuBar2(refIsResource, kMenuBarID, nil); 
  186.   SetSysBar(my_mbar_hndl); 
  187.   SetMenuBar(nil);
  188.  
  189.   /* now, add NDA's, adjust the sizes of the menus, and draw the menu bar */
  190.   /* kAppleMenuID used to be defined as a long and had to be cast to a */
  191.   /* word here.  It's been redefined to be only a word in size, so the */
  192.   /* casting is no longer needed. */
  193.   FixAppleMenu(kAppleMenuID); /* adds NDA's */
  194.   menu_bar_height =  FixMenuBar(); /* adjust the sizes */
  195.   DrawMenuBar();  /* draw the new menu bar and enjoy! */ 
  196.   }
  197. }
  198.  
  199. /* ------------------------------------------------------------------------ */
  200. /* the following procedure is responsible for starting the tools (using the */
  201. /* list in a resource) if the SartupTools call fails, then gPunt will */
  202. /* contain "TRUE", so we can abort the app the global variable for this */
  203. /* app's memory id is acquired here as well. */
  204.  
  205. do_init_rom()
  206. {
  207.     gMyMemID = _ownerid; /* find out our memory id & save it for later */
  208.  
  209.     /* crank 'em up! - make sure that kStartStopID is defined as a long!!! */
  210.     gToolListRef = StartUpTools(gMyMemID,refIsResource,kStartStopID);
  211.     
  212.     if (_toolErr == noError)
  213.       {      /* there was no error, so the app can continue starting up */
  214.         gPunt = FALSE;
  215.       }
  216.     else
  217.       {     /* something went wrong, so set gPunt to indicate the failure */
  218.         gPunt = TRUE;
  219.       }
  220.           
  221.           gWhichCursor = rFirstCursor; /* we're going to use a custom cursor */
  222. }
  223.  
  224.  
  225. /* ------------------------------------------------------------------------ */
  226. /* the following procedure draws the contents of the window that we created */
  227. /* from the template in the resource fork.  Any time the window's content */
  228. /* region needs to be redrawn, this routine gets called.  Put a SysBeep() */
  229. /* call in here if you want to investigate when this routine gets called. */
  230. /* That will cause a beep every time this routine gets called... */
  231.  
  232. drawMyContents()
  233. {
  234.         /* declare a couple of local variables that we'll need */
  235.         /* handle to an icon loaded from the resource fork */
  236.         QDIconRecordHndl  my_RHndl;
  237.         long              my_icon_id; /* resource ID of icon to be used */
  238.  
  239.  
  240.         /* initialize my_icon_id to use the "floor" icon */
  241.         my_icon_id = kFloorIcon;
  242.   
  243.         /* There are two ways to draw an icon on the screen.  The first one */
  244.         /* is to make a control that includes an icon in it and use */
  245.         /* "DrawControl" to draw it for us.  Since we just want to decorate */
  246.         /* our screen and don't really want to have controls, we're going to */
  247.         /* use the second way.  The second way is to use the toolbox call */
  248.         /* "DrawIcon" to draw it.  DrawIcon needs a pointer to the icon */
  249.         /* that's going to be drawn.  No problem - LoadResource gives us a */
  250.         /* handle to the icon, so we just dereference the handle and pass */
  251.         /* the resulting pointer to DrawIcon... */
  252.         
  253.         /* first we load the icon using the "LoadResource" toolbox call */
  254.         /* LoadResource returns a "handle" so we have to type cast it to */
  255.         /* QDIconRecordHndl */
  256.         my_RHndl =  (QDIconRecordHndl) LoadResource(rIcon, my_icon_id);
  257.                 
  258.         /* Lock the handle so it can't move while we're drawing */
  259.         HLock(my_RHndl);
  260.                 
  261.         /* next, we draw it at a fixed location using the "DrawIcon" toolbox call */
  262.         /* horz = 30, vert = 60 */
  263.         DrawIcon(*my_RHndl, 0, 30, 60);
  264.                 
  265.         /* Let's draw it in a bunch of different places.  The icon is six */
  266.         /* pixels wide, but we're using dithered pixels on the 640  screen, */
  267.         /* so we have to move over 12 pixels to prevent the icons from */
  268.         /* overlapping. */
  269.         DrawIcon(*my_RHndl, 0, 42, 60);
  270.         DrawIcon(*my_RHndl, 0, 54, 60);
  271.         DrawIcon(*my_RHndl, 0, 66, 60);
  272.         DrawIcon(*my_RHndl, 0, 78, 60);
  273.         DrawIcon(*my_RHndl, 0, 90, 60);
  274.         DrawIcon(*my_RHndl, 0,102, 60);
  275.         DrawIcon(*my_RHndl, 0,114, 60);
  276.         DrawIcon(*my_RHndl, 0,126, 60);
  277.         DrawIcon(*my_RHndl, 0,138, 60);
  278.         DrawIcon(*my_RHndl, 0, 78, 76); /* put this one away from the others */
  279.  
  280.         /* Unlock the handle - NEVER forget to unlock a handle you locked! */
  281.         HUnlock(my_RHndl);
  282. }
  283.  
  284.  
  285. /* ------------------------------------------------------------------------ */
  286. /* the following procedure creates a window using a template that is kept */
  287. /* in the application's resource fork */
  288.  
  289. do_make_window()
  290. {
  291.     /* since we only have one window and it can't be closed, we won't */
  292.     /* bother to keep the grafPortPtr in a global.  We can always get it */
  293.     /* back by calling FrontWindow().  Later, when we add multiple windows, */
  294.     /* we'll want a better way to keep track of the grafPortPtr to each */
  295.     /* window, but for now I'd like to keep it simple. */
  296.     
  297.  GrafPortPtr    myWndwPtr;
  298.     
  299.  myWndwPtr = NewWindow2(NIL, /* use "default" title string from param block */
  300.                         NIL, /* use "default" refCon from param block */
  301.                         drawMyContents, /* procedure that draws contents */
  302.                         NIL, /* use std def proc for this window */
  303.                         refIsResource,   /* template is in a resource */
  304.                         myWindowID,       /* resource ID of our window */
  305.                         rWindParam1);    /* template is of param type 1 */
  306.  
  307.   SetPort(myWndwPtr); /* set the Graf Port to the newly created window's */
  308. }
  309.  
  310. /* ------------------------------------------------------------------------ */
  311. /* the following procedure is the main event loop. It runs until gPunt is */
  312. /* set to TRUE by the user picking "Quit" from the File menu. */
  313.  
  314. do_main_event()
  315. {
  316.   word  myTaskCode;  /* used to hold the task codes returned by Task Master */
  317.   
  318.  
  319.   /* tell Task Master which events it can do */
  320.   /* we're lazy, so let it handle everything possible! */
  321.   gMyEvent.wmTaskMask = kMyTaskMask;
  322.  
  323.   while(!gPunt)  /* keep calling Task Master until "Quit" has been selected */
  324.   {
  325.     myTaskCode = TaskMaster(kMyEventMask, &gMyEvent);
  326.     switch(myTaskCode) 
  327.       {
  328.         case wInGoAway:
  329.            break;
  330.         case wInSpecial:
  331.         case wInMenuBar:
  332.            do_menu_events();
  333.             break;
  334.         default:  
  335.                         break; /* always have a default */
  336.       }    /* end of the switch statement */        
  337.     } /* end of the "while" */
  338. } /* end of do_main_event */
  339.  
  340.  
  341. /* ------------------------------------------------------------------------ */
  342. /* the following procedure is the main application itself. */
  343. /* don't forget to add the code that will check the message center to see if */
  344. /* this app was launched by clicking on its icon or by clicking on a data */
  345. /* file created by this app.  If the data file was clicked on, then grab its */
  346. /* name out of the message center and open it instead of opening the */
  347. /* untitled window. */
  348.  
  349. main()
  350. {    
  351.     do_init_rom();    /* get my memory id, start the tools, & set gPunt */
  352.     if (gPunt == FALSE)
  353.       {
  354.         do_make_menus();  /* insert the menu bar */
  355.         do_make_window(); /* create a new window from the resource fork */
  356.         InitCursor();     /* this changes the cursor to the "normal" one. */
  357.                           /* It was left as a watch cursor when the tools */
  358.                           /* were started up. */
  359.                 
  360.         /* Set the cursor to a custom one that's in the resource fork. */
  361.         /* To do this, we have to load it, lock the handle, call SetCursor */
  362.         /* and then unlock the handle. */
  363.         grCursorHndl = (CursorHndl) LoadResource(rCursor, (long) gWhichCursor); 
  364.         HLock(grCursorHndl);
  365.         SetCursor(*grCursorHndl);
  366.         HUnlock(grCursorHndl);
  367.  
  368.         do_main_event();
  369.       }
  370.     ShutDownTools(refIsHandle,gToolListRef); /* shut down the tools and quit */
  371. } /* end of main program */
  372.